package cn.geminis.crypto.core.util;

import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.openssl.MiscPEMGenerator;
import org.bouncycastle.util.io.pem.PemReader;
import org.bouncycastle.util.io.pem.PemWriter;

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;

/**
 * @author Allen
 */
public class EncodeUtils {

    public static String toPEM(Object obj) {
        try (StringWriter sw = new StringWriter();
             PemWriter writer = new PemWriter(sw)) {
            MiscPEMGenerator pemGenerator = new MiscPEMGenerator(obj);
            writer.writeObject(pemGenerator);
            writer.flush();
            return sw.toString();
        } catch (IOException e) {
            throw new RuntimeException("PEM格式编码错误", e);
        }
    }

    public static byte[] toDER(ASN1Object obj) {
        try {
            return obj.getEncoded();
        } catch (IOException e) {
            throw new RuntimeException("DER格式编码错误", e);
        }
    }

    public static ASN1Primitive fromDER(byte[] data) {
        try {
            ASN1InputStream stream = new ASN1InputStream(data);
            ASN1Primitive asn1 = stream.readObject();
            return asn1;
        } catch (IOException e) {
            throw new RuntimeException("DER格式解析错误", e);
        }
    }

    public static ASN1Encodable fromPEM(String data) {
        try (StringReader sr = new StringReader(data);
             PemReader reader = new PemReader(sr);) {
            byte[] der = reader.readPemObject().getContent();
            return fromDER(der);
        } catch (IOException e) {
            throw new RuntimeException("PEM格式解析错误", e);
        }
    }

    public static ASN1Encodable fromDERorPEM(byte[] data) {
        try {
            return fromDER(data);
        } catch (Exception eDer) {
            try {
                return fromPEM(new String(data));
            } catch (Exception ePem) {
                throw new RuntimeException("尝试解析数据，但该数据既不是DER格式，也不是PEM格式", eDer);
            }
        }
    }

}
